#region Imported Namespaces
using System;
using System.Data;
using System.Data.SqlClient;
using System.Collections;

using BO = PHSRAG.Insight21.BusinessObjects;
using DataAccess = PHSRAG.Utility.DataAccess;
using ICachePolicy = PHSRAG.Insight21.Policy.ICachePolicy;
using System.Text.RegularExpressions;
#endregion

namespace PHSRAG.Insight21.FormsManagement
{
	#region Class ItemOption
	/// <summary>
	/// ItemOption class abstracts the notion of an option to a QuestionnaireItem.
	/// Ex: Yes, No options are stored as ItemOptions for a question (QuestionnaireItem) which says "Does your study involve any radioactive material?"
	/// Options for a checkbox, a radiobutton question, a dropdownlist etc are stored in 
	/// ItemOption objects and are associated with their respective questions(QuestionnaireItem)
	/// </summary>
	public class ItemOption : BO.SmartBusinessObject, ICloneable
	{
		#region Constants
		private const string QuestionnaireItemOptionKey = "QuestionnaireItemOptionKey_91D4117B-A365-4e8f-9A25-813D64D17F5C";

		private const string ColumnNameId = "Id";
		private const string ColumnNameItemId = "ItemId";
		private const string ColumnNameOptionText = "OptionText";
		private const string ColumnNameOptionValue = "OptionValue";
		#endregion
		
		#region Instance Variables (Private)
		private int questionnaireItemId;
		private string optionText; 
		private string optionValue;
		#endregion

		#region Constructors
		/// <summary>
		/// Constructs a new ItemOption object based on the Cache Policy passed in as a parameter. 
		/// </summary>
		/// <param name="cachePolicy">The prevalent cache policy</param>
		public ItemOption(ICachePolicy cachePolicy) :  base(cachePolicy)
		{
		}
		
		
		/// <summary>
		/// Constructs a new ItemOption object based on the Cache Policy passed in as a parameter. 
		/// All the instance variables will be set to the corresponding values specified in the Data Row
		/// </summary>
		/// <param name="cachePolicy">The prevalent cache policy</param>
		/// <param name="dataRow">DataRow holding the values to be assigned to instance variables</param>
		public ItemOption(ICachePolicy cachePolicy, DataRow dataRow ) : base(cachePolicy)
		{
			Id	= (int)dataRow[ColumnNameId];
			questionnaireItemId = (int)dataRow[ColumnNameItemId];
			optionText = (string)dataRow[ColumnNameOptionText];
			optionValue	= (string)dataRow[ColumnNameOptionValue];
		}

		#endregion
		
        #region ICloneable
        object ICloneable.Clone()
        {
            return Clone();
        }
        #endregion

        public ItemOption Clone()
        {
            ItemOption option = (ItemOption)MemberwiseClone( );
            option.Id = 0;
            option.Dirty = true;

            return option;
        }
        
        #region Properties
		/// <summary>
		/// Gets or sets the QuestionnaireItem id of the ItemOption object
		/// </summary>
		public int QuestionnaireItemId
		{
			get	{ return questionnaireItemId; }
			set	{ SetDirty(ref questionnaireItemId, value);	}
		}

		
		/// <summary>
		/// Gets or sets the text visible to the user for the option
		/// </summary>
		public string OptionText
		{
			get	{ return optionText; }
			set	{ SetDirty(ref optionText, value); }
		}

		/// <summary>
		/// Gets the option text after stripping all the html tags
		/// </summary>
		public string HtmlStrippedOptionText
		{
			get { return (optionText != null) ? Regex.Replace(optionText, "<[^>]+>", string.Empty) : string.Empty; }
		}

		/// <summary>
		/// Gets or sets the value behind the text used to identify the option
		/// </summary>
		public string OptionValue
		{
			get	{ return optionValue; }
			set	{ SetDirty(ref optionValue, value);	}
		}
		#endregion

		#region Smart Business Object Methods
		/// <summary>
		/// Cache Key uniquely identifies this object within the cache.
		/// </summary>
		/// <returns>the unique string for this object</returns>
		public override string CacheKey()
		{
			return QuestionnaireItemOptionKey;
		}
		
		
		/// <summary>
		/// Cache this instance using the prevalent cache policy.
		/// </summary>
		public override void Cache()
		{
			CachePolicy.Cache(QuestionnaireItemOptionKey, this);
		}

		
		/// <summary>
		/// Remove this instance from the cache using the prevalent cache policy.
		/// </summary>
		public override void UnCache()
		{
			CachePolicy.UnCache(QuestionnaireItemOptionKey);
		}
		
		
		/// <summary>
		/// Loads the ItemOption based on the optional Args.
		/// <para>This method is not yet implemented</para> 
		/// </summary>
		/// <param name="connectionString">Information to connect to the database</param>
		/// <param name="args">ItemOption Id of the object to be loaded</param>
		public override void Load(string connectionString, params object[] args)
		{
			throw new Exception("Not Implemented");
		}
		
		
		/// <summary>
		/// Saves the state of the ItemOption object to the database. 
		/// The stored procedure inserts a new record if the id of the object is 0, 
		/// otherwise the procedure updates the record with the matching itemoption id
		/// </summary>
		/// <param name="sqlTransaction">The database context in which the underlying sql statement needs to be executed</param>
		protected override void SaveObject(SqlTransaction sqlTransaction)
		{
			try
			{
				if (Id != -1)
				{
					Id = Convert.ToInt32(Utility.DataAccess.ExecuteScalar(sqlTransaction.Connection,sqlTransaction, "SaveItemOption",
						Utility.DataAccess.BuildSqlParameterArray(
						"@id", SqlDbType.Int, Id
						,"@itemID", SqlDbType.Int, questionnaireItemId
						,"@optionText", SqlDbType.VarChar, optionText
						,"@optionValue", SqlDbType.VarChar, optionValue
						)));
				}
			}
			catch(Exception ex)
			{
				Utility.ExceptionReport.WriteToEventLog("ItemOption.SaveObject: Failed to save the ItemOption object to the database", 
					ex, true, Utility.ExceptionReport.ReportType.Error);
				throw new Exception("ItemOption.SaveObject: Failed to save the ItemOption object to the database", ex);
			}

		}
		
		
		/// <summary>
		/// Deletes the record represented by the object
		/// </summary>
		/// <param name="sqlTransaction">SQL transaction to use when deleting</param>
		protected override void DeleteObject(SqlTransaction sqlTransaction)
		{
			try
			{
				Utility.DataAccess.ExecuteNonQuery(sqlTransaction.Connection,sqlTransaction, "DeleteItemOption",
					Utility.DataAccess.BuildSqlParameterArray(
					"@id", SqlDbType.Int, Id
					));
			}
			catch(Exception ex)
			{
				Utility.ExceptionReport.WriteToEventLog("ItemOption.DeleteObject: Failed to delete the ItemOption object from the database", 
					ex, true, Utility.ExceptionReport.ReportType.Error);
				throw new Exception("ItemOption.DeleteObject: Failed to delete the ItemOption object from the database", ex);
			}

		}
		#endregion

		#region Static methods
		/// <summary>
		/// Gets all the item options associated with a QuestionnaireItem
		/// </summary>
		/// <param name="cachePolicy">The prevalent cache policy</param>
		/// <param name="itemID">QuestionnaireItem Id, the options of which have to be returned</param>
		/// <returns>A collection of ItemOption objects</returns>
		public  static ArrayList GetQuestionnaireItemOptions(ICachePolicy cachePolicy, int itemID)
		{
			ArrayList optionsList = new ArrayList();
			try
			{
				DataSet ds = Utility.DataAccess.GetDataSet(Utility.DataAccess.GetConnectionString(), "GetItemOptionsForItem", 
					Utility.DataAccess.BuildSqlParameterArray
					("@ItemID", SqlDbType.Int, itemID));
				if (ds.Tables.Count > 0)
				{
					foreach( DataRow row in ds.Tables[0].Rows )
					{
						optionsList.Add (new ItemOption(cachePolicy, row));
					}
				}
				else
				{
					throw new Exception("GetItemOptionsForItem stored procedure returned incorrect results");
				}
			}
			catch(Exception ex)
			{
				Utility.ExceptionReport.WriteToEventLog ("ItemOption.GetQuestionnaireItemOptions: Failed to load Questionnaire Item Options", ex, true, Utility.ExceptionReport.ReportType.Error);
				throw new Exception("ItemOption.GetQuestionnaireItemOptions: Failed to load Questionnaire Item Options", ex);
			}

			return optionsList;
		}


		/// <summary>
		/// Gets all the item options associated with a QuestionnaireItem
		/// </summary>
		/// <param name="cachePolicy">The prevalent cache policy</param>
		/// <param name="optionsRefDomain">Refdomain for the item options</param>
		/// <returns>A collection of ItemOption objects</returns>
		public  static ArrayList GetQuestionnaireItemOptions(ICachePolicy cachePolicy, string optionsRefDomain)
		{
			ArrayList optionsList = new ArrayList();
			try
			{
				DataSet ds = Utility.DataAccess.GetDataSet(Utility.DataAccess.GetConnectionString(), "GetItemOptionsForItemFromRefCode", 
					Utility.DataAccess.BuildSqlParameterArray
					("@optionsRefDomain", SqlDbType.VarChar, optionsRefDomain));
				if (ds.Tables.Count > 0)
				{
					foreach( DataRow row in ds.Tables[0].Rows )
					{
						optionsList.Add (new ItemOption(cachePolicy, row));
					}
				}
				else
				{
					throw new Exception("GetItemOptionsForItem stored procedure returned incorrect results");
				}
			}
			catch(Exception ex)
			{
				Utility.ExceptionReport.WriteToEventLog ("ItemOption.GetQuestionnaireItemOptions: Failed to load Questionnaire Item Options", ex, true, Utility.ExceptionReport.ReportType.Error);
				throw new Exception("ItemOption.GetQuestionnaireItemOptions: Failed to load Questionnaire Item Options", ex);
			}

			return optionsList;
		}
		#endregion
	}
	#endregion
}
